package ESP.Util;
/**
 * 建议使用SHA1算法加密，加密程度高，执行时间短。
 * @author 程尧
 */
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


public class Encryption{
	/**
	 * ——MD5加密算法
	 * @author 程尧
	 * @param 加密前字符串
	 * @return 加密后字符串
	 */
	public static String encryptionMD5(String unEncryptionStr) {
		MessageDigest md5 = null;
		char[] charArray = unEncryptionStr.toCharArray();
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			return "---加密时出错---：" + e.toString();
		}
		byte[] byteArray = new byte[charArray.length];
		for (int i = 0; i < charArray.length; i++) {
			byteArray[i] = (byte) charArray[i];
		}
		byte[] md5Bytes = md5.digest(byteArray);
		StringBuffer hexValue = new StringBuffer();
		for (int i = 0; i < md5Bytes.length; i++) {
			int val = ((int) md5Bytes[i]) & 0xff;
			if (val < 16) {
				hexValue.append("0");
			}
			hexValue.append(Integer.toHexString(val));
		}
		return hexValue.toString();
	}
	/**
	 * 
	 * ——SHA1加密算法
	 * 
	 * @author 程尧
	 * @param 加密前字符串
	 * @return 加密后字符串
	 */
	public static String encryptionSHA1(String unEncryptionStr) {
		final int[] abcde = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
		int[] digestInt = new int[5];// 摘要数据存储数组
		int[] tmpData = new int[80];// 计算过程中的临时数据存储数组
		/**
		 * 将字节数组转换为十六进制字符串
		 */
		byte[] bytearray;
		System.arraycopy(abcde, 0, digestInt, 0, abcde.length);// 初试化常量
		/**
		 * 格式化输入字节数组格式
		 */ 
		// 补0数量
		int zeros = 0;
		// 补位后总位数
		int size = 0;
		// 原始数据长度
		int n = unEncryptionStr.getBytes().length;
		// 模64后的剩余位数
		int m = n % 64;
		// 计算添加0的个数以及添加10后的总长度
		if (m < 56) {
			zeros = 55 - m;
			size = n - m + 64;
		} else if (m == 56) {
			zeros = 63;
			size = n + 8 + 64;
		} else {
			zeros = 63 - m + 56;
			size = (n + 64) - m + 64;
		}
		// 补位后生成的新数组内容
		byte[] newbyte = new byte[size];
		// 复制数组的前面部分
		System.arraycopy(unEncryptionStr.getBytes(), 0, newbyte, 0, n);
		// 获得数组Append数据元素的位置
		int l = n;
		// 补1操作
		newbyte[l++] = (byte) 0x80;
		// 补0操作
		for (int i = 0; i < zeros; i++) {
			newbyte[l++] = (byte) 0x00;
		}
		// 计算数据长度，补数据长度位共8字节，长整型
		long N = (long) n * 8;
		byte h8 = (byte) (N & 0xFF);
		byte h7 = (byte) ((N >> 8) & 0xFF);
		byte h6 = (byte) ((N >> 16) & 0xFF);
		byte h5 = (byte) ((N >> 24) & 0xFF);
		byte h4 = (byte) ((N >> 32) & 0xFF);
		byte h3 = (byte) ((N >> 40) & 0xFF);
		byte h2 = (byte) ((N >> 48) & 0xFF);
		byte h1 = (byte) (N >> 56);
		newbyte[l++] = h1;
		newbyte[l++] = h2;
		newbyte[l++] = h3;
		newbyte[l++] = h4;
		newbyte[l++] = h5;
		newbyte[l++] = h6;
		newbyte[l++] = h7;
		newbyte[l++] = h8;
		int MCount = newbyte.length / 64;// 获取数据摘要计算的数据单元个数
		// 循环对每个数据单元进行摘要计算
		for (int pos = 0; pos < MCount; pos++) {
			// 将每个单元的数据转换成16个整型数据，并保存到tmpData的前16个数组元素中
			for (int j = 0; j < 16; j++) {
				/**
				 *  4字节数组转换为整数
				 */
				int i = (pos * 64) + (j * 4);
				tmpData[j] = ((newbyte[i] & 0xff) << 24) | ((newbyte[i + 1] & 0xff) << 16) 
							| ((newbyte[i + 2] & 0xff) << 8) | (newbyte[i + 3] & 0xff);
			}
			/**
			 * 摘要计算函数
			 */
			for (int i = 16; i <= 79; i++) {
				int xx = tmpData[i - 3] ^ tmpData[i - 8] ^ tmpData[i - 14] ^ tmpData[i - 16];
				tmpData[i] = (xx<<1)|(xx>>>31);
			}
			int[] tmpabcde = new int[5];
			for (int i1 = 0; i1 < tmpabcde.length; i1++) {
				tmpabcde[i1] = digestInt[i1];
			}
			for (int j = 0; j <= 19; j++) {
				int tmp = ((tmpabcde[0]<<5)|(tmpabcde[0]>>>27))
						+ ((tmpabcde[1] & tmpabcde[2]) | (~tmpabcde[1] & tmpabcde[3])) + tmpabcde[4] + tmpData[j] + 0x5a827999;
				tmpabcde[4] = tmpabcde[3];
				tmpabcde[3] = tmpabcde[2];
				tmpabcde[2] = ((tmpabcde[1]<<30)|(tmpabcde[1]>>>2));
				tmpabcde[1] = tmpabcde[0];
				tmpabcde[0] = tmp;
			}
			for (int k = 20; k <= 39; k++) {
				int tmp = ((tmpabcde[0]<<5)|(tmpabcde[0]>>>27))
						+ (tmpabcde[1] ^ tmpabcde[2] ^ tmpabcde[3]) + tmpabcde[4] + tmpData[k] + 0x6ed9eba1;
				tmpabcde[4] = tmpabcde[3];
				tmpabcde[3] = tmpabcde[2];
				tmpabcde[2] = (tmpabcde[1]<<30)|(tmpabcde[1]>>>2);
				tmpabcde[1] = tmpabcde[0];
				tmpabcde[0] = tmp;
			}
			for (int q = 40; q <= 59; q++) {
				int tmp = ((tmpabcde[0]<< 5)|(tmpabcde[0]>>>27))
						+ ((tmpabcde[1]&tmpabcde[2])|(tmpabcde[1]&tmpabcde[3])|(tmpabcde[2]&tmpabcde[3]))+tmpabcde[4] + tmpData[q] + 0x8f1bbcdc;
				tmpabcde[4] = tmpabcde[3];
				tmpabcde[3] = tmpabcde[2];
				tmpabcde[2] = (tmpabcde[1]<<30)|(tmpabcde[1]>>>2);
				tmpabcde[1] = tmpabcde[0];
				tmpabcde[0] = tmp;
			}
			for (int w = 60; w <= 79; w++) {
				int tmp = ((tmpabcde[0]<<5)|(tmpabcde[0]>>>27))
						+ (tmpabcde[1] ^ tmpabcde[2] ^ tmpabcde[3]) + tmpabcde[4] + tmpData[w] + 0xca62c1d6;
				tmpabcde[4] = tmpabcde[3];
				tmpabcde[3] = tmpabcde[2];
				tmpabcde[2] = (tmpabcde[1]<<30)|(tmpabcde[1]>>>2);
				tmpabcde[1] = tmpabcde[0];
				tmpabcde[0] = tmp;
			}
			for (int i2 = 0; i2 < tmpabcde.length; i2++) {
				digestInt[i2] = digestInt[i2] + tmpabcde[i2];
			}
			for (int r = 0; r < tmpData.length; r++) {
				tmpData[r] = 0;
			}
		}
		byte[] digest = new byte[20];
		for (int i = 0; i < digestInt.length; i++) {
			// 整数转换为4字节数组
			digest[i * 4] = (byte) (digestInt[i] >>> 24);
			digest[i * 4 + 1] = (byte) (digestInt[i] >>> 16);
			digest[i * 4 + 2] = (byte) (digestInt[i] >>> 8);
			digest[i * 4 + 3] = (byte) digestInt[i];
		}
		bytearray = digest;
		StringBuffer strDigest = new StringBuffer("");
		for (int i = 0; i < bytearray.length; i++) {
			// 将字节转换为十六进制字符串
			char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
			char[] ob = new char[2];
			ob[0] = Digit[(bytearray[i] >>> 4) & 0X0F];
			ob[1] = Digit[bytearray[i] & 0X0F];
			String s = new String(ob);
			strDigest.append(s);
		}
		return strDigest.toString();
	}
	public static void main(String[] args) {
		System.out.println(encryptionSHA1("3109001447"));
		System.out.println(encryptionSHA1("3109001448"));
		System.out.println(encryptionSHA1("3109001449"));
		System.out.println(encryptionSHA1("3109001450"));
	}
}
